// SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
// SPDX-License-Identifier: Mulan PSL v2
package resource

import (
	"flag"
	"os"

	nbv1 "github.com/kubeflow/kubeflow/components/notebook-controller/api/v1"
	"gorm.io/gorm"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/kubernetes"
	restClient "k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"sigs.k8s.io/controller-runtime/pkg/client"
	k8ssconf "sigs.k8s.io/controller-runtime/pkg/client/config"

	"code.geniusai.org/notebook-manager/pkg/config"
	"code.geniusai.org/notebook-manager/pkg/entity"
	"code.geniusai.org/notebook-manager/pkg/log"
	"code.geniusai.org/notebook-manager/pkg/storage"
)

var (
	scheme = runtime.NewScheme()
)

type Manager struct {
	conf                *config.Conf
	db                  *gorm.DB
	k8sClient           *kubernetes.Clientset
	k8sControllerClient client.Client
	k8sConfig           *restClient.Config
	notebookStore       storage.NotebookStoreInterface
	pvcStore            storage.PvcStoreInterface
	//argoClient             client.ArgoClientInterface
	//k8sCoreClient          client.KubernetesCoreInterface
	//kfamClient             client.KFAMClientInterface
	//time                   util.TimeInterface
	//uuid                   util.UUIDGeneratorInterface
}

func NewStoreManager(notebookStore storage.NotebookStoreInterface) *Manager {
	return &Manager{notebookStore: notebookStore}
}

func NewManager(confData *config.Conf) *Manager {
	return &Manager{conf: confData}
}

func (m *Manager) Init() error {

	db, err := storage.NewMysqlDB(&m.conf.Mysql)
	if err != nil {
		return err
	}
	m.db = db
	if err = initTables(db); err != nil {
		return err
	}

	if err = m.initStore(db); err != nil {
		return err
	}

	if err = m.initK8sClient(); err != nil {
		return err
	}

	return nil
}

func (m *Manager) Close() error {
	//return m.db.Close()
	return nil
}

func initTables(db *gorm.DB) error {
	err := db.AutoMigrate(
		&entity.Notebook{},
		&entity.Pvc{},
		//&entity.VolumeMount{},
	)
	return err
}

func (m *Manager) initStore(db *gorm.DB) error {
	m.notebookStore = storage.NewNotebookStore(db)

	m.pvcStore = storage.NewPvcStore(db)
	return nil
}

func (m *Manager) initK8sClient() error {
	var clusterConfig *restClient.Config
	var err error
	if os.Getenv("env") == "prod" {
		clusterConfig, err = restClient.InClusterConfig()
	} else {
		flag.Set("kubeconfig", "+config")
		clusterConfig, err = clientcmd.BuildConfigFromFlags("", flag.Lookup("kubeconfig").Value.String())
	}

	if err != nil {
		log.Errorf("error: %v", err)
		return entity.NewErrorf(entity.NotebookErrorModule, entity.MsgK8sInClusterConfigFailed)
	}
	m.k8sConfig = clusterConfig
	clientSet, err := kubernetes.NewForConfig(clusterConfig)
	if err != nil {
		log.Errorf("error: %v", err)
		return entity.NewErrorf(entity.NotebookErrorModule, entity.MsgK8sInClusterConfigFailed)
	}
	m.k8sClient = clientSet
	k8sControllerClient, err := client.New(k8ssconf.GetConfigOrDie(),
		client.Options{Scheme: scheme})
	if err != nil {
		return err
	}
	m.k8sControllerClient = k8sControllerClient
	return nil
}

func init() {
	_ = nbv1.AddToScheme(scheme)
	_ = corev1.AddToScheme(scheme)
}
